#pragma once 

#include <iostream>
#include <queue>
#include <pthread.h>

#define NUM 5

template <typename T>
class ThreadPool
{
  private:
    int thread_num;
    pthread_mutex_t lock;
    pthread_cond_t cond;
    std::queue<T> task_queue;
  public:
    ThreadPool(int _num = NUM): thread_num(_num)
    {
      pthread_mutex_init(&lock, nullptr);
      pthread_cond_init(&cond, nullptr);
    }

    void LockQueue()
    {
      pthread_mutex_lock(&lock);
    }

    void UnlockQueue()
    {
      pthread_mutex_unlock(&lock);
    }

    bool IsQueueEmpty()
    {
      return task_queue.size() == 0 ? true : false;
    }

    void Wakeup()  //唤醒线程
    {
      pthread_cond_signal(&cond);
    }

    void Wait()
    {
      pthread_cond_wait(&cond, &lock);
    }

    //static 静态方法 属于类 
    static void *Rountine(void *arg)
    {
      pthread_detach(pthread_self());
      ThreadPool *self = (ThreadPool*)arg;
      while(true)
      {
        self->LockQueue();
        while(self->IsQueueEmpty())
        {
          //wait
          self->Wait();
        }
        T t;
        self->Pop(t);
        self->UnlockQueue();

        //处理任务TODO
        t.Run();
      }
    }

    void InitThreadPool()
    {
      pthread_t tid;
      for(int i = 0; i < thread_num; i++)
      {
        pthread_create(&tid, nullptr,  Rountine, this);
        //pthread_detach(tid);
      }
    }

    void Push(const T& in)
    {
      LockQueue();
      // 任务
      task_queue.push(in); 
      UnlockQueue();
      Wakeup();
    }

    void Pop(T& out)
    {
      out = task_queue.front();
      task_queue.pop();
    }

    ~ThreadPool()
    {
      pthread_cond_destroy(&cond);
      pthread_mutex_destroy(&lock);
    }

};
